﻿using System;
using System.Html;
using Quicklight.Web.Html;
using jQueryApi;

namespace Quicklight.Web.Razor {

   /// <summary>
   /// Does the binding on behalf of a declarative binding of a ObservableProperty to an attribute on an element
   /// For example <input type="text" @Binding("value", ViewModel.X) />
   /// </summary>
   /// <typeparam name="T">Type of the wrapped field of the ObservableProperty</typeparam>
   public class ObservablePropertyAttributeBinder<T> : AttributeBinder {
      private ObservableProperty<T> property;
      private string triggerElementId;
      private string eventName;
      private bool updateModel;
      private bool updateUI;

      /// <summary>
      /// Constructs a ObservablePropertyAttributeBinder for binding the ObservableProperty to the attribute 
      /// </summary>
      /// <param name="attributeName">Name of attribute to bind to</param>
      /// <param name="property">ObservableProperty to bind to attribute</param>
      /// <param name="triggerElementId">If the element that has the trigger event is an element other than the element of the attribute, specify its id here</param>
      /// <param name="eventName">Name of the event that will trigger an update from the UI to the model</param>
      /// <param name="updateModel">Boolean indicating if the trigger event occurs whether the ObservableProperty must be updated with the value of the attribute</param>
      /// <param name="updateUI">Boolean indicating if changes in the ObservableProperty must propagate to the attribute</param>
      public ObservablePropertyAttributeBinder(string attributeName, ObservableProperty<T> property, string triggerElementId, string eventName, bool updateModel, bool updateUI)
         : base(attributeName) {

         this.property = property;
         this.triggerElementId = triggerElementId;
         this.eventName = eventName;
         this.updateModel = updateModel;
         this.updateUI = updateUI;
      }

      /// <summary>
      /// Bind method does the actual binding of the ObservableProperty to the attribute of the specified element
      /// </summary>
      /// <param name="element">Element with which the binding must occur</param>
      protected override void Bind(Element element) {
         element.Bind<T>(attributeName, property, triggerElementId, eventName, updateModel, updateUI);

         if (updateUI) {
            jQueryObject jQueryObject = jQuery.FromElement(element);
            jQueryObject.Attribute(attributeName, property.Value.ToString());
         }
      }
   }
}
